package fun.hijklmn.magic.admin.server.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import fun.hijklmn.magic.admin.common.pojo.Permission;
import fun.hijklmn.magic.admin.common.pojo.RolePermission;
import fun.hijklmn.magic.admin.common.vo.req.PermissionReqVO;
import fun.hijklmn.magic.admin.server.constants.RedisKeyConstant;
import fun.hijklmn.magic.admin.server.dao.PermissionDao;
import fun.hijklmn.magic.admin.server.enums.PermissionTypeEnum;
import fun.hijklmn.magic.admin.server.service.PermissionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import fun.hijklmn.magic.admin.server.service.RolePermissionService;
import fun.hijklmn.magic.common.enums.StatusEnum;
import fun.hijklmn.magic.common.exception.MagicBizException;
import fun.hijklmn.magic.idGenerator.client.api.IdGeneratorServiceApi;
import fun.hijklmn.magic.idGenerator.common.enums.ServerTypeEnum;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zsl
 * @since 2021-06-25
 */
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionDao, Permission> implements PermissionService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IdGeneratorServiceApi idGeneratorServiceApi;

    @Autowired
    private RolePermissionService rolePermissionService;

    @Override
    public Permission save(PermissionReqVO permissionReqVO) {

        QueryWrapper<Permission> permissionQueryWrapper = new QueryWrapper<>();

        if (StringUtils.isNotEmpty(permissionReqVO.getRequestUrl())) {
            permissionQueryWrapper.eq("request_url", permissionReqVO.getRequestUrl());
        }

        permissionQueryWrapper.eq("is_delete", 0);

        List<Permission> permissionList = this.list(permissionQueryWrapper);

        LocalDateTime curLocalDateTime = LocalDateTime.now();

        if (StringUtils.isNotEmpty(permissionReqVO.getId())) {

            if (permissionList.stream().filter(permission -> permissionReqVO.getId().equals(permission.getId())).count() > 0) {
                throw new MagicBizException("改权限已经存在");
            }

            if (redisTemplate.hasKey(RedisKeyConstant.roleId_Permissions.concat(permissionReqVO.getId()))) {
                redisTemplate.delete(RedisKeyConstant.roleId_Permissions.concat(permissionReqVO.getId()));
            }

            Permission updatePermission = new Permission();

            if (StringUtils.isNotEmpty(permissionReqVO.getName())) {
                updatePermission.setName(permissionReqVO.getName());
            }

            if (permissionReqVO.getType() != null && PermissionTypeEnum.containType(permissionReqVO.getType())) {
                updatePermission.setType(permissionReqVO.getType());
            }

            if (StringUtils.isNotEmpty(permissionReqVO.getIcon())) {
                updatePermission.setIcon(permissionReqVO.getIcon());
            }

            if (StringUtils.isNotEmpty(permissionReqVO.getRequestUrl())) {
                updatePermission.setRequestUrl(permissionReqVO.getRequestUrl());
            }

            if (StringUtils.isNotEmpty(permissionReqVO.getParentId())) {
                updatePermission.setParentId(permissionReqVO.getParentId());
            }

            if (permissionReqVO.getSort() != null) {
                updatePermission.setSort(permissionReqVO.getSort());
            }

            updatePermission.setUpdateTime(curLocalDateTime);

            this.update(updatePermission, new UpdateWrapper<Permission>().eq("id", permissionReqVO.getId()));

            return updatePermission;

        } else {

            if (StringUtils.isNotEmpty(permissionReqVO.getRequestUrl())) {
                throw new MagicBizException("请输入访问路径");
            }

            if (permissionReqVO.getType() == null) {
                throw new MagicBizException("请输入权限类型");
            }

            if (!PermissionTypeEnum.containType(permissionReqVO.getType())) {
                throw new MagicBizException("权限类型输入错误");
            }

            Permission insertPermission = new Permission();

            BeanUtils.copyProperties(permissionReqVO, insertPermission);

            insertPermission.setIsDelete(StatusEnum.RecordValidEnum.normal.isDelete());

            insertPermission.setCreateTime(curLocalDateTime);

            insertPermission.setId(idGeneratorServiceApi.get(ServerTypeEnum.admin_server));

            this.save(insertPermission);

            return insertPermission;

        }

    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public void delete(String permissionId) {

        QueryWrapper<Permission> permissionQueryWrapper = new QueryWrapper<>();
        permissionQueryWrapper.eq("is_delete", 0);
        permissionQueryWrapper.eq("id", permissionId);
        permissionQueryWrapper.last("limit 1");

        Permission permission = this.getOne(permissionQueryWrapper);
        if (permission == null || permission.getIsDelete()) {
            throw new MagicBizException("该权限已经被删除");
        }

        QueryWrapper<RolePermission> rolePermissionQueryWrapper = new QueryWrapper<>();
        rolePermissionQueryWrapper.eq("is_delete", 0);
        rolePermissionQueryWrapper.eq("permission_id", permissionId);

        List<RolePermission> rolePermissionList = rolePermissionService.list(rolePermissionQueryWrapper);

        List<String> roleIds = rolePermissionList.stream().map(RolePermission::getRoleId).collect(Collectors.toList());

        LocalDateTime curLocalDateTime = LocalDateTime.now();

        RolePermission updateRolePermission = new RolePermission();
        updateRolePermission.setUpdateTime(curLocalDateTime);
        updateRolePermission.setIsDelete(StatusEnum.RecordValidEnum.deleted.isDelete());
        rolePermissionService.update(updateRolePermission, new UpdateWrapper<RolePermission>().in("role_id", roleIds));

        Permission updatePermission = new Permission();
        updatePermission.setUpdateTime(curLocalDateTime);
        updatePermission.setIsDelete(StatusEnum.RecordValidEnum.deleted.isDelete());
        this.update(updatePermission, new QueryWrapper<Permission>().eq("id", permissionId));

        roleIds.stream().forEach(roleId -> {
            if (redisTemplate.hasKey(RedisKeyConstant.roleId_Permissions.concat(roleId))) {
                redisTemplate.delete(RedisKeyConstant.roleId_Permissions.concat(roleId));
            }
        });

    }

}
